package com.example.demo.security;

// import com.example.demo.security.AdminDetailsServiceImpl; // 管理员用户，也需要注入
import io.jsonwebtoken.ExpiredJwtException;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;

@Component
public class JwtRequestFilter extends OncePerRequestFilter {

    private static final Logger log = LoggerFactory.getLogger(JwtRequestFilter.class);

    @Autowired
    @Qualifier("userDetailsServiceImpl") // 普通用户的 UserDetailsService
    private UserDetailsService regularUserDetailsService;

    @Autowired
    @Qualifier("adminDetailsServiceImpl") // 管理员的 UserDetailsService
    private UserDetailsService adminUserDetailsService;

    @Autowired
    private JwtUtil jwtUtil;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException {

        log.debug("JwtRequestFilter: Processing request for URI: {}", request.getRequestURI());

        final String authorizationHeader = request.getHeader("Authorization");
        String username = null;
        String jwt = null;

        if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
            jwt = authorizationHeader.substring(7);
            try {
                username = jwtUtil.extractUsername(jwt);
            } catch (IllegalArgumentException e) {
                log.warn("JwtRequestFilter: Unable to get JWT Token or JWT is malformed.", e);
            } catch (ExpiredJwtException e) {
                log.warn("JwtRequestFilter: JWT Token has expired. Subject: '{}'", e.getClaims().getSubject());
            } catch (Exception e) {
                log.error("JwtRequestFilter: Error parsing JWT Token.", e);
            }
        } else {
            // 只有当不是明确允许匿名访问的路径（如登录、注册）时才记录警告
            String uri = request.getRequestURI();
            if (!uri.endsWith("/login") && !uri.endsWith("/register")) {
                log.trace("JwtRequestFilter: Authorization header does not exist or does not begin with 'Bearer ' for URI: {}", uri);
            }
        }

        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
            UserDetails userDetails = null;
            String userType = "unknown"; // 用于日志记录

            // 尝试确定用户类型或按顺序尝试 UserDetailsService
            // 这是一个简化处理，更健壮的方案可能是在JWT中包含用户类型声明
            try {
                // 优先尝试管理员 (如果路径是 /api/admin/**) 或基于其他逻辑
                // 或者简单地按顺序尝试
                if (request.getRequestURI().startsWith("/api/admin/")) {
                    userDetails = this.adminUserDetailsService.loadUserByUsername(username);
                    userType = "admin";
                } else {
                    userDetails = this.regularUserDetailsService.loadUserByUsername(username);
                    userType = "regular";
                }
            } catch (UsernameNotFoundException e) {
                // 如果第一次尝试失败，尝试另一个 (这假设用户名在两个服务中是唯一的，或者有一个明确的区分)
                log.warn("JwtRequestFilter: User '{}' not found with first UserDetailsService attempt ({}). Trying alternative.", username, userType);
                try {
                    if ("admin".equals(userType)) { // 如果第一次尝试的是admin失败了
                        userDetails = this.regularUserDetailsService.loadUserByUsername(username);
                        userType = "regular (fallback)";
                    } else { // 如果第一次尝试的是regular失败了
                        userDetails = this.adminUserDetailsService.loadUserByUsername(username);
                        userType = "admin (fallback)";
                    }
                } catch (UsernameNotFoundException ex) {
                    log.warn("JwtRequestFilter: User '{}' not found with alternative UserDetailsService either.", username, ex);
                }
            }


            if (userDetails != null) {
                log.debug("JwtRequestFilter: UserDetails loaded for username '{}' as type '{}'. Authorities: {}", username, userType, userDetails.getAuthorities());
                try {
                    if (jwtUtil.validateToken(jwt, userDetails)) {
                        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
                                userDetails, null, userDetails.getAuthorities());
                        usernamePasswordAuthenticationToken
                                .setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                        SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
                        log.info("JwtRequestFilter: Authentication set for user '{}' (type {}).", username, userType);
                    } else {
                        log.warn("JwtRequestFilter: JWT token validation failed for user '{}' (type {}).", username, userType);
                    }
                } catch (Exception e) {
                    log.error("JwtRequestFilter: Exception during token validation or setting authentication for user '{}' (type {}).", username, userType, e);
                }
            } else {
                log.warn("JwtRequestFilter: UserDetails is null for username '{}', cannot validate token or set authentication.", username);
            }
        }
        chain.doFilter(request, response);
    }
}
